<template>
  <div class="app-container" @keydown.delete="deleteSelectedElement" @keydown.ctrl.z="undo" @keydown.ctrl.y="redo" tabindex="0">
    <!-- 左边面板 -->
    <div class="left-panel" :style="{ width: leftWidth + 'px' }">
      <div>
        <el-button type="primary" size="small" icon="Edit" @click="saveComponent">确定</el-button>
      </div>
      <el-collapse v-model="activeGroup" accordion>
        <el-collapse-item
            key="sysLogicGroup"
            title="系统逻辑组"
            name="0"
        >
          <template #title>
            <img :src="sysLogicGroup" class="icon"  />
            <span>系统逻辑</span>
          </template>
          <div class="toolbar-group">
            <el-tooltip effect="dark" content="带箭头直线" placement="right">
              <el-button
                  circle
                  @click="toggleDrawingMode"
                  :type="isDrawingMode ? 'primary' : ''">
                <svg width="16" height="16" viewBox="0 0 24 24" style="stroke-width:1.5px">
                  <path d="M5 12H19M19 12L15 8M19 12L15 16"
                        stroke="currentColor"
                        stroke-linecap="round"/>
                </svg>
              </el-button>
            </el-tooltip>
            <!-- 在系统逻辑组中添加菱形图标 -->
            <el-tooltip effect="dark" content="菱形" placement="right">
              <el-button circle draggable="true" @dragstart="onDragStart($event, { objectType: 'diamond', isConnection: false })">
                <svg width="16" height="16" viewBox="0 0 16 16">
                  <path d="M8 0 L16 8 L8 16 L0 8 Z" fill="#409EFF"/>
                </svg>
              </el-button>
            </el-tooltip>
            <!-- 新增返回图标 -->
            <el-tooltip effect="dark" content="返回" placement="right">
              <el-button circle draggable="true" @dragstart="onDragStart($event, { objectType: 'return', isConnection: false })">
                <svg t="1749373495692" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1498" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 0C229.229617 0 0 229.229617 0 512s229.229617 512 512 512 512-229.230708 512-512S794.769292 0 512 0z m232.727074 640.000818a186.182314 186.182314 0 0 1-186.182314 186.181223 26.996746 26.996746 0 1 1 0-53.992402 131.258275 131.258275 0 0 0 131.258275-131.258275v-69.818231A131.258275 131.258275 0 0 0 558.545851 438.923221H353.280251l127.535 93.090611a27.137474 27.137474 0 1 1-32.116387 43.753122l-186.182314-139.636462a26.996746 26.996746 0 0 1-6.051277-37.701845l6.051277-6.051277 186.182314-139.636463a27.461474 27.461474 0 0 1 37.701845 6.516004 26.530928 26.530928 0 0 1-5.585458 36.771299l-115.433537 88.902609H558.545851A186.182314 186.182314 0 0 1 744.728165 571.113133z" fill="#1296db" p-id="1499"></path></svg>
              </el-button>
            </el-tooltip>
          </div>
        </el-collapse-item>
        <!-- 其他复合组件分组 -->
        <el-collapse-item
            v-for="(group, index) in processedGroupIconUrls"
            :key="group.groupId"
            :title="group.groupName"
            :name="index"
        >
          <template #title>
            <img :src="group.groupIconUrl" class="icon"  />
            <span>{{ group.groupName }}</span>
          </template>
          <div class="toolbar-group">
            <el-tooltip effect="dark" v-for="(element, index) in group.tenantComponents" :content="element.componentName" placement="right" >
              <el-button circle draggable="true" @dragstart="onDragStart($event, element)">
                <img :src="element.componentIconUrl" draggable="false"  class="icon" :alt="element.componentName" />
              </el-button>
            </el-tooltip>
          </div>
        </el-collapse-item>
      </el-collapse>
    </div>

    <!-- 分隔条 -->
    <div class="splitter" @mousedown="startResize"></div>

    <!-- 右边面板 -->
    <div class="right-panel" @dragover.prevent @drop="onDrop">
      <!-- SVG 画布 -->
      <div class="svg-container">
        <svg :style="{ width: svgWidth + 'px', height: svgHeight + 'px' }" @click="handleSvgClick"
             @mousemove="handleSvgMouseMove" ref="svgCanvas">
          <!-- 绘制所有组件元素 -->
          <g v-for="(item, index) in svgElements" :key="index" @click.stop="selectElement(index, $event)">
            <component
                v-for="(child, childIndex) in item.children"
                :key="childIndex"
                :is="child.type"
                v-bind="child.attrs"
            >
              {{ child.text }}
            </component>
            <!-- 选中时显示把柄 -->
            <g v-if="item.selected">
              <!-- 虚线框 -->
              <rect
                  :x="item.children[0].attrs.x - 5"
                  :y="item.children[0].attrs.y - 5"
                  :width="item.children[0].attrs.width + 10"
                  :height="item.children[0].attrs.height + 10"
                  fill="none"
                  stroke="blue"
                  stroke-width="2"
                  stroke-dasharray="5"
              />
              <!-- 八个控制点（把柄） -->
              <!-- 左上角 -->
              <circle
                  :cx="item.children[0].attrs.x"
                  :cy="item.children[0].attrs.y"
                  r="5"
                  fill="blue"
                  @mousedown.stop="startResizeElement(index, 'top-left', $event)"

                  style="cursor: nwse-resize;"
              />
              <!-- 上边中点 -->
              <circle
                  :cx="item.children[0].attrs.x + item.children[0].attrs.width / 2"
                  :cy="item.children[0].attrs.y"
                  r="5"
                  fill="blue"
                  @mousedown.stop="startResizeElement(index, 'top', $event)"

                  style="cursor: ns-resize;"
              />
              <!-- 右上角 -->
              <circle
                  :cx="item.children[0].attrs.x + item.children[0].attrs.width"
                  :cy="item.children[0].attrs.y"
                  r="5"
                  fill="blue"
                  @mousedown.stop="startResizeElement(index, 'top-right', $event)"

                  style="cursor: nesw-resize;"
              />
              <!-- 右边中点 -->
              <circle
                  :cx="item.children[0].attrs.x + item.children[0].attrs.width"
                  :cy="item.children[0].attrs.y + item.children[0].attrs.height / 2"
                  r="5"
                  fill="blue"
                  @mousedown.stop="startResizeElement(index, 'right', $event)"

                  style="cursor: ew-resize;"
              />
              <!-- 右下角 -->
              <circle
                  :cx="item.children[0].attrs.x + item.children[0].attrs.width"
                  :cy="item.children[0].attrs.y + item.children[0].attrs.height"
                  r="5"
                  fill="blue"
                  @mousedown.stop="startResizeElement(index, 'bottom-right', $event)"

                  style="cursor: nwse-resize;"
              />
              <!-- 下边中点 -->
              <circle
                  :cx="item.children[0].attrs.x + item.children[0].attrs.width / 2"
                  :cy="item.children[0].attrs.y + item.children[0].attrs.height"
                  r="5"
                  fill="blue"
                  @mousedown.stop="startResizeElement(index, 'bottom', $event)"

                  style="cursor: ns-resize;"
              />
              <!-- 左下角 -->
              <circle
                  :cx="item.children[0].attrs.x"
                  :cy="item.children[0].attrs.y + item.children[0].attrs.height"
                  r="5"
                  fill="blue"
                  @mousedown.stop="startResizeElement(index, 'bottom-left', $event)"

                  style="cursor: nesw-resize;"
              />
              <!-- 左边中点 -->
              <circle
                  :cx="item.children[0].attrs.x"
                  :cy="item.children[0].attrs.y + item.children[0].attrs.height / 2"
                  r="5"
                  fill="blue"
                  @mousedown.stop="startResizeElement(index, 'left', $event)"

                  style="cursor: ew-resize;"
              />
              <!-- 中间把柄（用于移动） -->
              <circle
                  :cx="item.children[0].attrs.x + item.children[0].attrs.width / 2"
                  :cy="item.children[0].attrs.y + item.children[0].attrs.height / 2"
                  r="5"
                  fill="green"
                  @mousedown.stop="startMoveElement(index, $event)"

                  style="cursor: move;"
              />
            </g>
          </g>

          <!-- 绘制所有箭头 -->
          <!-- 修改 defs 中的箭头标记 -->
          <defs>
            <marker
                id="arrow"
                markerWidth="10"
                markerHeight="10"
                refX="9"
                refY="3"
                orient="auto"
                markerUnits="strokeWidth"
            >
              <path
                  d="M0,0 L0,6 L9,3 z"
                  :fill="selectedArrow?.stroke || 'black'"
                  @mousedown.stop="startArrowDrag(conn, $event)"
                  style="cursor: move;"
              />
            </marker>
            <!-- 吸附点标记 -->
            <marker
                id="snap-point"
                markerWidth="8"
                markerHeight="8"
                refX="4"
                refY="4"
                orient="auto"
            >
              <circle cx="4" cy="4" r="3" fill="none" stroke="#FF5722" stroke-width="1" />
            </marker>
          </defs>

          <!-- 渲染所有连线 -->
          <g v-for="(conn, index) in connections" :key="'conn-'+index"       >
            <!-- 折线路径 -->
            <!-- 修改连线渲染部分 -->
            <path
                :d="conn.path"
                :stroke="conn === selectedArrow ? '#409EFF' : conn.stroke || 'black'"
                :stroke-width="conn === selectedArrow ? 3 : conn.strokeWidth || 2"
                fill="none"
                :marker-end="'url(#arrow)'"
                @click="handleLineClick(conn, $event)"
                @mousedown="handleLineClick(conn, $event)"
                @dblclick="handleLineDoubleClick(conn, $event)"
                class="conn-line"
                :class="{
            'active-line': conn === selectedArrow,
            'dragging-line': conn.isDragging
            }"
                style="pointer-events: visiblePainted;"
            />
            <!-- 在连线中间显示条件表达式 -->
            <text
                v-if="conn.condition && isDiamondStart(conn.startElementId)"
                :x="getConnectionMidpoint(conn).x"
                :y="getConnectionMidpoint(conn).y"
                text-anchor="middle"
                dominant-baseline="middle"
                fill="#333"
                font-size="10"
                style="pointer-events: none; user-select: none;"
                class="connection-condition"
            >
              {{ conn.condition }}
            </text>
            <!-- 控制点（只在选中时显示） -->
            <circle
                v-for="(point, pIndex) in conn.points"
                :style="{ opacity: conn === selectedArrow ? 1 : 0 }"
                :key="'point-'+index+'-'+pIndex"
                :cx="point.x"
                :cy="point.y"
                r="5"
                fill="#409EFF"
                @mousedown.stop="startDragLine(index, pIndex, $event)"
                @dblclick.stop="deleteControlPoint(conn, pIndex, $event)"
                @mouseenter="setHandleCursor"
                @mouseleave="resetCursor"
                class="conn-handle"
                style="cursor: move;"
            />
          </g>
          <!-- 渲染所有菱形 -->
          <g v-for="(item, index) in diamondElements" :key="index" >
            <!-- 添加透明点击热区（填充透明但可点击） -->
            <path
                :d="`M${item.points[0].x},${item.points[0].y} L${item.points[1].x},${item.points[1].y} L${item.points[2].x},${item.points[2].y} L${item.points[3].x},${item.points[3].y} Z`"
                fill="transparent"
                stroke="none"
                @click.stop="selectDiamond(index, $event)"
                style="pointer-events: all;"
            />
            <!-- 修改菱形渲染部分 -->
            <path
                :d="`M${item.points[0].x},${item.points[0].y} L${item.points[1].x},${item.points[1].y} L${item.points[2].x},${item.points[2].y} L${item.points[3].x},${item.points[3].y} Z`"
                :fill="item.attrs.fill"
                :stroke="item.selected ? '#409EFF' : item.attrs.stroke"
                :stroke-width="item.selected ? 2 : item.attrs['stroke-width']"
                :transform="item.attrs.rotate ? `rotate(${item.attrs.rotate} ${(item.points[1].x + item.points[3].x)/2} ${(item.points[0].y + item.points[2].y)/2})` : ''"
                @click.stop="selectDiamond(index, $event)"
            />
            <!-- 菱形控制点 -->
            <g v-if="item.selected">
              <!-- 四个顶点控制点 -->
              <circle v-for="(point, pIndex) in item.points" :key="'vertex-'+pIndex"
                      :cx="point.x" :cy="point.y" r="5" fill="#409EFF"
                      @mousedown.stop="startResizeDiamond(index, pIndex, $event)"
                      :style="{
      cursor: ['nwse-resize', 'nesw-resize', 'nwse-resize', 'nesw-resize'][pIndex]
    }"
              />

              <!-- 四个边中点控制点 -->
              <circle v-for="(edge, eIndex) in [
    { pos: 0, cursor: 'ns-resize' }, // 上
    { pos: 1, cursor: 'ew-resize' }, // 右
    { pos: 2, cursor: 'ns-resize' }, // 下
    { pos: 3, cursor: 'ew-resize' }  // 左
  ]" :key="'edge-'+eIndex"
                      :cx="(item.points[eIndex].x + item.points[(eIndex+1)%4].x)/2"
                      :cy="(item.points[eIndex].y + item.points[(eIndex+1)%4].y)/2"
                      r="5" fill="#409EFF"
                      @mousedown.stop="startResizeDiamondEdge(index, eIndex, $event)"
                      :style="{ cursor: edge.cursor }"
              />

              <!-- 中心控制点 -->
              <circle
                  :cx="(item.points[0].x + item.points[2].x)/2"
                  :cy="(item.points[0].y + item.points[2].y)/2"
                  r="5" fill="#67C23A"
                  @mousedown.stop="startMoveDiamond(index, $event)"
                  style="cursor: move;"
              />
            </g>
          </g>
        </svg>
      </div>
    </div>

    <!-- 属性页面（右边） -->
    <div class="property-panel">
      <el-tabs type="border-card">
        <el-tab-pane label="通用属性">
          <el-form v-if="selectedElement" label-width="80px">
            <el-form-item label="X 坐标">
              <el-input-number v-model="cX" :min="0" :max="svgWidth" :disabled="!selectedElement?.children?.[0]"  />
            </el-form-item>
            <el-form-item label="Y 坐标">
              <el-input-number v-model="cY" :min="0" :max="svgHeight" :disabled="!selectedElement?.children?.[0]" />
            </el-form-item>
            <el-form-item label="宽度">
              <el-input-number v-model="cWidth" :min="10" :max="500" :disabled="!selectedElement?.children?.[0]" />
            </el-form-item>
            <el-form-item label="高度">
              <el-input-number v-model="cHeight" :min="10" :max="500" :disabled="!selectedElement?.children?.[0]"  />
            </el-form-item>
            <el-form-item label="填充颜色">
              <el-color-picker v-model="cFill" />
            </el-form-item>
            <el-form-item label="边框颜色">
              <el-color-picker v-model="cStroke" />
            </el-form-item>
            <el-form-item label="边框宽度">
              <el-input-number v-model="strokeWidth1" :min="1" :max="10"  :disabled="!selectedElement?.children?.[0]" />
            </el-form-item>
          </el-form>
          <div v-else class="empty-tip">请选择一个元素以编辑属性</div>
        </el-tab-pane>
        <el-tab-pane label="组件属性">
          <div v-if="selectedElement?.objectType ==='component'">
            <!-- 功能点下拉列表 -->
            <el-select
                v-model="selectedElement.children[2].attrs.selectedFunctionPoint"
                placeholder="请选择功能点"
                @change="handleFunctionPointChange"
                clearable
            >
              <el-option
                  v-for="point in functionPoints"
                  :key="point.functionCode"
                  :label="point.functionName"
                  :value="point.functionCode"
              />
            </el-select>

            <!-- 功能点参数列表表格 -->
            <el-table
                :data="selectedElement.children[2].attrs.functionPointParams"
                style="width: 100%; margin-top: 20px;"
                border
            >
              <el-table-column prop="parameterName" label="参数名称" />
              <el-table-column prop="parameterType" label="参数类型" />
              <el-table-column label="参数值">
                <template #default="scope">
                  <el-input
                      v-model="scope.row.value"
                      placeholder="请输入参数值"
                      size="small"
                  />
                </template>
              </el-table-column>
              <el-table-column prop="parameterDesc" label="参数描述" />
            </el-table>
            <!-- 返回值名称输入框 -->
            <el-form-item label="返回值名称" style="margin-top: 20px;">
              <el-input
                  v-model="selectedElement.children[2].attrs.returnValueName"
                  placeholder="请输入返回值名称"
                  style="width: 300px;"
              />
            </el-form-item>
            <!-- 新增备注输入框 -->
            <el-form-item label="备注" style="margin-top: 20px;">
              <el-input
                  v-model="selectedElement.children[2].attrs.remark"
                  type="textarea"
                  placeholder="请输入备注信息"
                  :rows="2"
                  style="width: 100%;"
              />
            </el-form-item>
          </div>
        </el-tab-pane>
        <!-- 在属性面板的箭头属性选项卡中添加开关 -->
        <el-tab-pane label="连线属性" v-if="selectedArrow">
          <el-form label-width="80px">
            <!-- 新增条件表达式 -->
            <el-form-item label="条件表达式" v-if="selectedArrow.startElementId && isDiamondStart(selectedArrow.startElementId)">
              <el-input
                  v-model="selectedArrow.condition"
                  placeholder="例如: amount > 100"
                  clearable
              />
            </el-form-item>
            <el-form-item label="启用吸附">
              <el-switch v-model="isSnappingEnabled" />
            </el-form-item>
            <el-form-item label="吸附阈值">
              <el-input-number
                  v-model="SNAP_THRESHOLD"
                  :min="1"
                  :max="20"
                  :step="1"
              /> px
            </el-form-item>
            <el-form-item label="箭头颜色">
              <el-color-picker v-model="selectedArrow.stroke" />
            </el-form-item>
            <el-form-item label="箭头宽度">
              <el-input-number v-model="selectedArrow.strokeWidth" :min="1" :max="10" />
            </el-form-item>
            <el-form-item label="起点连接">
              <el-tag v-if="selectedArrow.startElementId?.startsWith('component-') || selectedArrow.startElementId?.startsWith('return-')">
                组件: {{ selectedArrow.startElementId }}
              </el-tag>
              <el-tag v-else-if="selectedArrow.startElementId?.startsWith('diamond-')" type="warning">
                菱形: {{ selectedArrow.startElementId }}
              </el-tag>
              <el-tag v-else-if="selectedArrow.startElementId?.startsWith('conn-')" type="success">
                连线: {{ selectedArrow.startElementId }}
              </el-tag>

              <span v-else>未连接</span>
            </el-form-item>

            <el-form-item label="终点连接">
              <el-tag v-if="selectedArrow.endElementId?.startsWith('component-')||selectedArrow.endElementId?.startsWith('return-')">
                组件: {{ selectedArrow.endElementId }}
              </el-tag>
              <el-tag v-else-if="selectedArrow.endElementId?.startsWith('diamond-')" type="warning">
                菱形: {{ selectedArrow.endElementId }}
              </el-tag>
              <el-tag v-else-if="selectedArrow.endElementId?.startsWith('conn-')" type="success">
                连线: {{ selectedArrow.endElementId }}
              </el-tag>
              <span v-else>未连接</span>
            </el-form-item>
            <!-- 新增备注输入框 -->
            <el-form-item label="备注">
              <el-input
                  v-model="selectedArrow.remark"
                  type="textarea"
                  placeholder="请输入备注信息"
                  :rows="2"
                  style="width: 100%;"
              />
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <!-- 在属性面板的el-tabs中添加菱形属性 -->
        <el-tab-pane label="菱形属性" v-if="selectedElement?.objectType  === 'diamond'">
          <el-form label-width="auto">
            <el-form-item label="填充颜色">
              <el-color-picker v-model="selectedElement.attrs.fill" />
            </el-form-item>
            <el-form-item label="边框颜色">
              <el-color-picker v-model="selectedElement.attrs.stroke" />
            </el-form-item>
            <el-form-item label="边框宽度">
              <el-input-number
                  v-model="selectedElement.attrs['stroke-width']"
                  :min="1"
                  :max="10"
              />
            </el-form-item>
            <el-form-item label="宽度">
              <el-input-number
                  v-model="diamondWidth"
                  :min="20"
                  :max="500"
                  @change="updateDiamondSize"
              />
            </el-form-item>
            <el-form-item label="高度">
              <el-input-number
                  v-model="diamondHeight"
                  :min="20"
                  :max="500"
                  @change="updateDiamondSize"
              />
            </el-form-item>
            <!-- 新增备注输入框 -->
            <el-form-item label="备注">
              <el-input
                  v-model="selectedElement.attrs.remark"
                  type="textarea"
                  placeholder="请输入备注信息"
                  :rows="2"
                  style="width: 100%;"
              />
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <el-tab-pane label="返回属性" v-if="selectedElement?.objectType === 'return'">
          <el-form label-width="80px">
            <el-form-item label="返回值">
              <el-input
                  v-model="selectedElement.returnValue"
                  placeholder="请输入返回值"
                  clearable
              />
            </el-form-item>
          </el-form>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>

<script lang="ts" setup>
import {ref, onMounted, onUnmounted, computed, watch} from 'vue';
import { ElMessage, ElCollapse, ElCollapseItem, ElTooltip, ElButton, ElMessageBox, ElTabs, ElTabPane, ElForm, ElFormItem, ElInputNumber, ElColorPicker } from 'element-plus';
import { listAllGroup } from '@/api/business/tenantcomponentgroup';
import { listNoPageFunction as listNoPageSysFunction } from '@/api/business/sysfunction';
import { listParametersNoPage as listSysFunctionParameters } from '@/api/business/sysfunctionparameters';
import { useRoute } from "vue-router";
import { listParametersNoPage } from "@/api/business/teantfunctionparameters";
import { AxiosResponse } from "axios";
import sysLogicGroup from '@/assets/icons/svg/ali_logic.svg';
import {useIcon} from "@/components/common/util";

const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

// SVG 的宽度和高度
const svgWidth = ref(800); // 初始宽度
const svgHeight = ref(600); // 初始高度
// 左边面板宽度
const leftWidth = ref(200);
// 是否正在调整宽度
const isResizing = ref(false);
// 当前展开的组
const activeGroup = ref(0);
const svgElements = ref([]);
// 分隔栏最后x位置
const lastMoveX = ref(0);
const route = useRoute();
const functionId = ref(route.params.componentId);
// 获取当前网页请求的 IP 或域名
const servername = window.location.hostname;
const isDrawingMode = ref(false);
const drawingStartElement = ref(null);
const drawingStartElement1 = ref(null);
const drawingStartPort = ref(null);
const tempLine = ref(null);

const submitIcon = useIcon("ali_check")


// 工具栏分组数据
const toolbarGroups = ref<{
  groupId: string;
  groupCode: string;
  groupName: string;
  groupIconUrl: string;
  tenantComponents: {
    componentId: string;
    componentName: string;
    componentIconUrl: string;
  }[];
}[]>([]);
interface Connection {
  id: string;                   // 唯一标识
  points: { x: number; y: number }[]; // 所有控制点（不再区分虚实）
  path: string;                 // 动态计算的路径
  isDragging?: boolean; // 新增拖动状态
  dragOffset?: { x: number; y: number }; // 拖动偏移量
  stroke?: string;      // 线条颜色
  strokeWidth?: number; // 线条宽度
  startElementId?: string;      // 绑定的起点元素
  endElementId?: string;        // 绑定的终点元素
  condition?: string; // 新增条件表达式属性
  remark?: string; // 新增备注属性
}
// 撤销/重做栈
const undoStack = ref<any[]>([]);
const redoStack = ref<any[]>([]);

// 当前选中的元素
const selectedElement = ref<any>(null);


//连线
const connections = ref<Connection[]>([]);
//菱形（判断框)
const diamondElements = ref<any[]>([]);
// 当前选中的箭头
const selectedArrow = ref<any>(null);
// 添加辅助方法判断起点是否是菱形
const isDiamondStart = (elementId: string) => {
  return diamondElements.value.some(d => d.id === elementId);
};
// 添加获取连线中点的方法
const getConnectionMidpoint = (conn: Connection) => {
  if (conn.points.length === 0) return { x: 0, y: 0 };

  // 对于简单直线
  if (conn.points.length === 2) {
    return {
      x: (conn.points[0].x + conn.points[1].x) / 2,
      y: (conn.points[0].y + conn.points[1].y) / 2
    };
  }

  // 对于折线，取中间点
  const midIndex = Math.floor(conn.points.length / 2);
  return {
    x: conn.points[midIndex].x,
    y: conn.points[midIndex].y
  };
};
const loadDesignData = async () => {
  try {

    // let rootElement = {"svgElements":svgElements.value, "connections":connections.value}
    console.log("loadDesignData",props.modelValue)
    if(props.modelValue) {
      let rootElement = JSON.parse(props.modelValue);
      if (rootElement.svgElements) {
        svgElements.value = rootElement.svgElements;
        if (svgElements.value == null) {
          svgElements.value = [];
        }
      } else {
        svgElements.value = [];
      }
      if (rootElement.connections) {
        connections.value = rootElement.connections;
        if (connections.value == null) {
          connections.value = [];
        }
      } else {
        connections.value = [];
      }
      if (rootElement.diamondElements) {
        diamondElements.value = rootElement.diamondElements;
        if (diamondElements.value == null) {
          diamondElements.value = []
        }
      } else {
        diamondElements.value = []
      }
    }else{
      diamondElements.value = []
      connections.value = [];
      svgElements.value = [];
    }
  } catch (e) {
    console.error('Failed to load design data:', e);
    ElMessage.error("加载设计图失败");
  }
};
watch(
    () => props.modelValue,
    (newVal) => {
      if(newVal!="") {
        loadDesignData()
      }else{
        console.log("design data newVal==''")
      }
    },
    { deep: true, immediate: true }
)

const updateDiamondExpression = (diamond) => {
  const index = diamondElements.value.findIndex(d => d.id === diamond.id);
  if (index >= 0) {
    // 使用Vue.set确保响应式更新
    diamondElements.value[index].expression = diamond.expression;
    // 强制更新视图
    diamondElements.value = [...diamondElements.value];
  }
};
// 只添加连线相关的方法
const toggleDrawingMode = () => {
  isDrawingMode.value = !isDrawingMode.value;
  if (!isDrawingMode.value) {
    resetDrawingState();
  }
};
const resetDrawingState = () => {
  drawingStartElement.value = null;
  drawingStartPort.value = null;
  if (tempLine.value && svgCanvas.value?.contains(tempLine.value)) {
    svgCanvas.value.removeChild(tempLine.value);
    tempLine.value = null;
  }
};
const handleSvgClick = (event: MouseEvent) => {
  // 获取实际点击的SVG元素
  const target = event.target as Element;

  // 原有的选择清除逻辑
  if (!isDrawingMode.value) {
    if (!selectedArrow.value) {
      clearSelection();
    }
    return;
  }

  // 防止事件冒泡影响其他逻辑
  event.stopPropagation();
  const svgRect = svgCanvas.value.getBoundingClientRect();
  const x = event.clientX - svgRect.left;
  const y = event.clientY - svgRect.top;

  const clickedElement =  findClickedElement(x, y);
  if (!drawingStartElement.value) {
    // 第一次点击 - 设置起点
    // 需要根据点击位置找到对应的元素

    if (!clickedElement) return;

    drawingStartElement.value = clickedElement;
    drawingStartElement1.value = clickedElement;
    drawingStartPort.value = target.classList.contains('port') ? target : null;

    // 创建临时连线
    tempLine.value = document.createElementNS('http://www.w3.org/2000/svg', 'line');
    tempLine.value.setAttribute('class', 'temp-line');
    tempLine.value.setAttribute('stroke', '#999');
    tempLine.value.setAttribute('stroke-width', '2');
    tempLine.value.setAttribute('stroke-dasharray', '5,5');
    svgCanvas.value.appendChild(tempLine.value);
    tempLine.value.setAttribute('marker-end', 'url(#arrow)');

    // 设置起点坐标
    let startX, startY;
    if (clickedElement.objectType === 'diamond') {
      // 菱形使用中心点作为起点
      const centerX = (clickedElement.points[0].x + clickedElement.points[2].x)/2;
      const centerY = (clickedElement.points[1].y + clickedElement.points[3].y)/2;
      startX = centerX;
      startY = centerY;
    } else {
      // 普通元素使用最近的吸附点
      const rect = event.currentTarget.getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;
      const result = findNearestSnapPointInObject(clickedElement, x, y);
      startX = result?.x;
      startY = result?.y;
    }

    tempLine.value.setAttribute('x1', startX);
    tempLine.value.setAttribute('y1', startY);
    tempLine.value.setAttribute('x2', startX);
    tempLine.value.setAttribute('y2', startY);
  } else {
    // 第二次点击 - 完成连线
    const endElement = clickedElement;
    if (!endElement) return;

    console.log('drawingStartElement:'+JSON.stringify(drawingStartElement.value))
    console.log('endElement:'+JSON.stringify(endElement))

    // 确保不是同一个元素
    if (endElement !== drawingStartElement.value) {
      // 检查是否已存在相同起点和终点的连线
      const existingConnection = connections.value.find(conn =>
          conn.startElementId === drawingStartElement.value.id &&
          conn.endElementId === endElement.id
      );

      if (existingConnection) {
        ElMessage.warning('这两个对象之间已经存在连线');
        resetDrawingState();
        return;
      }

      // 获取当前临时线的坐标
      const startX = parseFloat(tempLine.value.getAttribute('x1'));
      const startY = parseFloat(tempLine.value.getAttribute('y1'));
      const endX = parseFloat(tempLine.value.getAttribute('x2'));
      const endY = parseFloat(tempLine.value.getAttribute('y2'));

      // 计算虚线与目标元素的交点
      const intersection = findIntersectionWithElement(
          { x: startX, y: startY },
          { x: endX, y: endY },
          endElement
      );

      // 使用交点作为结束点，如果没有交点则使用点击位置
      const finalEndX = intersection ? intersection.x : endX;
      const finalEndY = intersection ? intersection.y : endY;

      const newConn = {
        id: `conn-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
        points: [
          { x: startX, y: startY },
          { x: finalEndX, y: finalEndY }
        ],
        path: `M${startX},${startY} L${finalEndX},${finalEndY}`,
        stroke: '#000000',
        strokeWidth: 2,
        startElementId: drawingStartElement.value.id,
        endElementId: endElement.id
      };
      connections.value.push(newConn);
    }

    resetDrawingState();
  }
};
// 新增辅助函数：计算线段与元素的交点
const findIntersectionWithElement = (startPoint, endPoint, element) => {
  // 获取元素的边界点
  const elementPoints = getElementBoundaryPoints(element);

  let closestIntersection = null;
  let minDistance = Infinity;

  // 检查与元素每条边的交点
  for (let i = 0; i < elementPoints.length; i++) {
    const elemStart = elementPoints[i];
    const elemEnd = elementPoints[(i + 1) % elementPoints.length];

    const intersection = calculateIntersection(
        { x1: startPoint.x, y1: startPoint.y, x2: endPoint.x, y2: endPoint.y },
        { x1: elemStart.x, y1: elemStart.y, x2: elemEnd.x, y2: elemEnd.y }
    );

    if (intersection) {
      // 计算交点到起点的距离，选择最近的交点
      const distance = Math.sqrt(
          Math.pow(intersection.x - startPoint.x, 2) +
          Math.pow(intersection.y - startPoint.y, 2)
      );

      if (distance < minDistance) {
        minDistance = distance;
        closestIntersection = intersection;
      }
    }
  }

  return closestIntersection;
};
// 获取元素的边界点（矩形或菱形）
const getElementBoundaryPoints = (element) => {
  if (element.objectType === 'diamond') {
    return element.points;
  } else if(element.objectType === 'component'||element.objectType === 'return') {
    const rect = element.children[0].attrs;
    return [
      { x: rect.x, y: rect.y },
      { x: rect.x + rect.width, y: rect.y },
      { x: rect.x + rect.width, y: rect.y + rect.height },
      { x: rect.x, y: rect.y + rect.height }
    ];
  }else{
    return element.points;
  }
};

/**
 * 根据鼠标点击坐标判断点击的是哪个对象
 * @param x 鼠标点击的x坐标
 * @param y 鼠标点击的y坐标
 * @returns 被点击的对象或null
 */
const findClickedElement = (x: number, y: number) => {
  // 点击检测容差范围
  const tolerance = 5;

  // 1. 首先检查菱形元素
  for (let i = diamondElements.value.length - 1; i >= 0; i--) {
    const diamond = diamondElements.value[i];
    if (isPointInDiamond(x, y, diamond, tolerance)) {
      return diamond;
    }
  }

  // 2. 检查SVG元素（包括组件和返回元素）
  for (let i = svgElements.value.length - 1; i >= 0; i--) {
    const element = svgElements.value[i];
    if (isPointInRect(x, y, element, tolerance)) {
      return element;
    }
  }

  // 3. 检查连线元素
  for (let i = connections.value.length - 1; i >= 0; i--) {
    const conn = connections.value[i];
    if (isPointOnLine(x, y, conn, tolerance)) {
      return conn;
    }
  }

  return null;
};

/**
 * 判断点是否在菱形内部或附近
 * @param x 点的x坐标
 * @param y 点的y坐标
 * @param diamond 菱形对象
 * @param tolerance 容差范围
 * @returns 是否在菱形内或附近
 */
const isPointInDiamond = (x: number, y: number, diamond: any, tolerance: number): boolean => {
  // 使用射线法判断点是否在菱形内部
  const points = diamond.points;
  let inside = false;

  for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
    const xi = points[i].x, yi = points[i].y;
    const xj = points[j].x, yj = points[j].y;

    const intersect = ((yi > y) !== (yj > y))
        && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
    if (intersect) inside = !inside;
  }

  if (inside) return true;

  // 检查点是否在菱形的边上（容差范围内）
  for (let i = 0; i < points.length; i++) {
    const p1 = points[i];
    const p2 = points[(i + 1) % points.length];
    if (distancePointToLine(x, y, p1.x, p1.y, p2.x, p2.y) <= tolerance) {
      return true;
    }
  }

  return false;
};

/**
 * 判断点是否在矩形内部或附近
 * @param x 点的x坐标
 * @param y 点的y坐标
 * @param element SVG元素
 * @param tolerance 容差范围
 * @returns 是否在矩形内或附近
 */
const isPointInRect = (x: number, y: number, element: any, tolerance: number): boolean => {
  if (!element.children || !element.children[0] || !element.children[0].attrs) return false;

  const rect = element.children[0].attrs;
  const x1 = rect.x, y1 = rect.y;
  const x2 = rect.x + rect.width, y2 = rect.y + rect.height;

  // 检查点是否在矩形内部
  if (x >= x1 && x <= x2 && y >= y1 && y <= y2) {
    return true;
  }

  // 检查点是否在矩形边缘附近（容差范围内）
  // 上边
  if (distancePointToLine(x, y, x1, y1, x2, y1) <= tolerance) return true;
  // 右边
  if (distancePointToLine(x, y, x2, y1, x2, y2) <= tolerance) return true;
  // 下边
  if (distancePointToLine(x, y, x1, y2, x2, y2) <= tolerance) return true;
  // 左边
  if (distancePointToLine(x, y, x1, y1, x1, y2) <= tolerance) return true;

  return false;
};

/**
 * 判断点是否在线段上或附近
 * @param x 点的x坐标
 * @param y 点的y坐标
 * @param conn 连线对象
 * @param tolerance 容差范围
 * @returns 是否在线段上或附近
 */
const isPointOnLine = (x: number, y: number, conn: Connection, tolerance: number): boolean => {
  const points = conn.points;

  for (let i = 0; i < points.length - 1; i++) {
    const p1 = points[i];
    const p2 = points[i + 1];

    if (distancePointToLine(x, y, p1.x, p1.y, p2.x, p2.y) <= tolerance) {
      return true;
    }
  }

  return false;
};

/**
 * 计算点到线段的距离
 * @param px 点的x坐标
 * @param py 点的y坐标
 * @param x1 线段起点x坐标
 * @param y1 线段起点y坐标
 * @param x2 线段终点x坐标
 * @param y2 线段终点y坐标
 * @returns 点到线段的距离
 */
const distancePointToLine = (
    px: number, py: number,
    x1: number, y1: number,
    x2: number, y2: number
): number => {
  const A = px - x1;
  const B = py - y1;
  const C = x2 - x1;
  const D = y2 - y1;

  const dot = A * C + B * D;
  const lenSq = C * C + D * D;
  let param = -1;

  if (lenSq !== 0) {
    param = dot / lenSq;
  }

  let xx, yy;

  if (param < 0) {
    xx = x1;
    yy = y1;
  } else if (param > 1) {
    xx = x2;
    yy = y2;
  } else {
    xx = x1 + param * C;
    yy = y1 + param * D;
  }

  const dx = px - xx;
  const dy = py - yy;
  return Math.sqrt(dx * dx + dy * dy);
};


// 计算两条线段的交点（原有函数保持不变）
const calculateIntersection = (line1, line2) => {
  const x1 = line1.x1, y1 = line1.y1, x2 = line1.x2, y2 = line1.y2;
  const x3 = line2.x1, y3 = line2.y1, x4 = line2.x2, y4 = line2.y2;

  const den = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
  if (den === 0) return null;

  const ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / den;
  const ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / den;

  if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
    return {
      x: x1 + ua * (x2 - x1),
      y: y1 + ua * (y2 - y1)
    };
  }
  return null;
};
const handleSvgMouseMove = (event) => {
  if (isDrawingMode.value && drawingStartElement.value && tempLine.value) {
    console.log('handleSvgMouseMove');
    const svgRect = svgCanvas.value.getBoundingClientRect();
    // const rect = event.currentTarget.getBoundingClientRect();
    const endX = event.clientX - svgRect.left;
    const endY = event.clientY - svgRect.top;

    let result = findNearestSnapPointInObject(drawingStartElement1.value,endX,endY);
    const startX =  result?.x;
    const startY = result?.y;
    tempLine.value.setAttribute('x1', startX);
    tempLine.value.setAttribute('y1', startY);
    tempLine.value.setAttribute('x2', endX);
    tempLine.value.setAttribute('y2', endY);
  }
};



// 计算属性，处理 group.groupIconUrl
const processedGroupIconUrls = computed(() => {
  return toolbarGroups.value.map(group => {
    return {
      ...group,
      groupIconUrl: group.groupIconUrl.startsWith('http') ? group.groupIconUrl : `http://${servername}:9300${group.groupIconUrl}`,
      tenantComponents: group.tenantComponents.map(element => {
        return {
          ...element,
          componentIconUrl: element.componentIconUrl.startsWith('http') ? element.componentIconUrl : `http://${servername}:9300${element.componentIconUrl}`
        };
      })
    };
  });
});
// 计算属性 - 菱形宽度
const diamondWidth = computed({
  get() {
    if (!selectedElement.value?.objectType  === 'diamond') return 0;
    return Math.abs(selectedElement.value.points[1].x - selectedElement.value.points[3].x);
  },
  set(value) {
    // 通过updateDiamondSize方法处理
  }
});
const cStroke = computed({
  get() {
    return selectedElement.value?.children?.[0]?.attrs?.['stroke'] || '#000000';
  },
  set(value) {
    if (selectedElement.value?.children?.[0]) {
      selectedElement.value.children[0].attrs['stroke'] = value;
    }
  }
});

const cFill = computed({
  get() {
    return selectedElement.value?.children?.[0]?.attrs?.['fill'] || 'white';
  },
  set(value) {
    if (selectedElement.value?.children?.[0]) {
      selectedElement.value.children[0].attrs['fill'] = value;
    }
  }
});

const cHeight = computed({
  get() {
    return selectedElement.value?.children?.[0]?.attrs?.['height'] || 50;
  },
  set(value) {
    if (selectedElement.value?.children?.[0]) {
      selectedElement.value.children[0].attrs['height'] = value;
    }
  }
});
const cWidth = computed({
  get() {
    return selectedElement.value?.children?.[0]?.attrs?.['width'] || 100;
  },
  set(value) {
    if (selectedElement.value?.children?.[0]) {
      selectedElement.value.children[0].attrs['width'] = value;
    }
  }
});

const cY = computed({
  get() {
    return selectedElement.value?.children?.[0]?.attrs?.['y'] || 1;
  },
  set(value) {
    if (selectedElement.value?.children?.[0]) {
      selectedElement.value.children[0].attrs['y'] = value;
    }
  }
});
const cX = computed({
  get() {
    return selectedElement.value?.children?.[0]?.attrs?.['x'] || 1;
  },
  set(value) {
    if (selectedElement.value?.children?.[0]) {
      selectedElement.value.children[0].attrs['x'] = value;
    }
  }
});

const strokeWidth1 = computed({
  get() {
    return selectedElement.value?.children?.[0]?.attrs?.['stroke-width'] || 1;
  },
  set(value) {
    if (selectedElement.value?.children?.[0]) {
      selectedElement.value.children[0].attrs['stroke-width'] = value;
    }
  }
});

// 计算属性 - 菱形高度
const diamondHeight = computed({
  get() {
    if (!selectedElement.value?.objectType  === 'diamond') return 0;
    return Math.abs(selectedElement.value.points[2].y - selectedElement.value.points[0].y);
  },
  set(value) {
    // 通过updateDiamondSize方法处理
  }
});

// 计算属性 - 旋转角度
const diamondRotation = computed({
  get() {
    return selectedElement.value?.attrs?.rotate || 0;
  },
  set(value) {
    rotateDiamond(value);
  }
});

// 更新菱形大小
const updateDiamondSize = () => {
  if (!selectedElement.value?.objectType  === 'diamond') return;

  const diamond = selectedElement.value;
  const centerX = (diamond.points[1].x + diamond.points[3].x) / 2;
  const centerY = (diamond.points[0].y + diamond.points[2].y) / 2;

  // 更新四个顶点位置
  diamond.points[0].x = centerX;
  diamond.points[0].y = centerY - diamondHeight.value/2;

  diamond.points[1].x = centerX + diamondWidth.value/2;
  diamond.points[1].y = centerY;

  diamond.points[2].x = centerX;
  diamond.points[2].y = centerY + diamondHeight.value/2;

  diamond.points[3].x = centerX - diamondWidth.value/2;
  diamond.points[3].y = centerY;

  // 应用旋转（如果存在）
  if (diamondRotation.value !== 0) {
    rotateDiamond(diamondRotation.value);
  }
};

// 旋转菱形
const rotateDiamond = (degrees) => {
  if (!selectedElement.value?.objectType  === 'diamond') return;

  const diamond = selectedElement.value;
  const centerX = (diamond.points[1].x + diamond.points[3].x) / 2;
  const centerY = (diamond.points[0].y + diamond.points[2].y) / 2;

  // 保存旋转角度
  diamond.attrs.rotate = degrees;

  // 计算旋转弧度
  const radians = degrees * Math.PI / 180;
  const cos = Math.cos(radians);
  const sin = Math.sin(radians);

  // 原始未旋转的点（基于当前大小）
  const originalPoints = [
    { x: centerX, y: centerY - diamondHeight.value/2 },
    { x: centerX + diamondWidth.value/2, y: centerY },
    { x: centerX, y: centerY + diamondHeight.value/2 },
    { x: centerX - diamondWidth.value/2, y: centerY }
  ];

  // 应用旋转
  originalPoints.forEach((point, index) => {
    // 转换为以中心点为原点的坐标
    const x = point.x - centerX;
    const y = point.y - centerY;

    // 应用旋转矩阵
    const rotatedX = x * cos - y * sin;
    const rotatedY = x * sin + y * cos;

    // 转换回画布坐标
    diamond.points[index].x = rotatedX + centerX;
    diamond.points[index].y = rotatedY + centerY;
  });
};
// 开始调整菱形大小
// 顶点调整（保持对角线垂直平分）
const startResizeDiamond = (index: number, pointIndex: number, event: MouseEvent) => {
  const diamond = diamondElements.value[index];
  const center = {
    x: (diamond.points[0].x + diamond.points[2].x)/2,
    y: (diamond.points[1].y + diamond.points[3].y)/2
  };

  let lastPos = { x: event.clientX, y: event.clientY };

  const onMouseMove = (e: MouseEvent) => {
    const deltaX = e.clientX - lastPos.x;
    const deltaY = e.clientY - lastPos.y;
    lastPos = { x: e.clientX, y: e.clientY };

    // 移动当前顶点
    diamond.points[pointIndex].x += deltaX;
    diamond.points[pointIndex].y += deltaY;

    // 计算对称顶点位置（保持对角线交叉）
    const oppositeIndex = (pointIndex + 2) % 4;
    diamond.points[oppositeIndex].x = center.x * 2 - diamond.points[pointIndex].x;
    diamond.points[oppositeIndex].y = center.y * 2 - diamond.points[pointIndex].y;

    // 调整相邻顶点保持菱形特性
    const nextIndex = (pointIndex + 1) % 4;
    const prevIndex = (pointIndex + 3) % 4;

    diamond.points[nextIndex].x = center.x + (center.y - diamond.points[pointIndex].y);
    diamond.points[nextIndex].y = center.y - (center.x - diamond.points[pointIndex].x);

    diamond.points[prevIndex].x = center.x - (center.y - diamond.points[pointIndex].y);
    diamond.points[prevIndex].y = center.y + (center.x - diamond.points[pointIndex].x);
  };

  const onMouseUp = () => {
    window.removeEventListener('mousemove', onMouseMove);
    window.removeEventListener('mouseup', onMouseUp);
  };

  window.addEventListener('mousemove', onMouseMove);
  window.addEventListener('mouseup', onMouseUp);
};

// 开始移动菱形
const startMoveDiamond = (index: number, event: MouseEvent) => {
  const diamond = diamondElements.value[index];
  const centerX = (diamond.points[0].x + diamond.points[2].x)/2;
  const centerY = (diamond.points[1].y + diamond.points[3].y)/2;

  let lastX = event.clientX;
  let lastY = event.clientY;

  const onMouseMove = (e: MouseEvent) => {
    const deltaX = e.clientX - lastX;
    const deltaY = e.clientY - lastY;
    lastX = e.clientX;
    lastY = e.clientY;

    // 移动所有点
    diamond.points.forEach(point => {
      point.x += deltaX;
      point.y += deltaY;
    });

    // 递归更新所有关联的连线
    updateAllConnectedLines(diamond.id, deltaX, deltaY);
  };

  const onMouseUp = () => {
    window.removeEventListener('mousemove', onMouseMove);
    window.removeEventListener('mouseup', onMouseUp);
  };

  window.addEventListener('mousemove', onMouseMove);
  window.addEventListener('mouseup', onMouseUp);
};
// 获取工具栏数据
const fetchToolbarData = async () => {
  try {
    const response = await listAllGroup();
    toolbarGroups.value = response.data;
  } catch (error) {
    console.error('Failed to fetch toolbar data:', error);
  }
};



const onDragStart = (event: any, item: any) => {
  event.dataTransfer.setData('text/plain', JSON.stringify(item));
};

const onDrop = (event: any) => {
  const data = JSON.parse(event.dataTransfer.getData('text/plain'));
  if(data.objectType =='component') {
    const rect = event.currentTarget.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;

    const newElement = getSVGContent(data, x, y);
    if(!svgElements.value){
      svgElements.value = [];
    }
    svgElements.value.push(newElement);
    // 动态调整 SVG 容器的宽度
    const contentWidth = x + 100; // 假设内容宽度为 200
    // 动态调整 SVG 尺寸
    const contentHeight = y + 100; // 假设内容高度为 100
    if (contentWidth > svgWidth.value) {
      svgWidth.value = contentWidth;
    }
    if (contentHeight > svgHeight.value) {
      svgHeight.value = contentHeight;
    }
    // 记录操作到撤销栈
    undoStack.value.push([...svgElements.value]);
  }else{
    //连线
    // if(data.objectType =='connection') {
    //   const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
    //   const x = event.clientX - rect.left;
    //   const y = event.clientY - rect.top;
    //   const newConn = createConnection(x, y);
    //  // 检查是否从某个元素拖出（自动绑定起点）
    //   const startElement = findNearestSnapPoint (x, y);
    //   if (startElement) {
    //     newConn.startElementId = startElement.elementId || undefined;
    //   }
    //   connections.value.push(newConn);
    // }else
    if(data.objectType =='diamond'){
      const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;
      const newElement = createDiamond(x, y);
      diamondElements.value.push(newElement);
    }
    // 处理返回对象的创建
    if(data.objectType === 'return') {
      const rect = event.currentTarget.getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;

      const newElement = createReturnElement(x, y);
      if(!svgElements.value){
        svgElements.value = [];
      }
      svgElements.value.push(newElement);
      return;
    }
  }
  redoStack.value = []; // 清空重做栈
};

const createDiamond = (x: number, y: number) => {
  const width = 60; // 初始宽度
  const height = 60; // 初始高度

  return {
    id: `diamond-${Date.now()}`,
    objectType: 'diamond',
    attrs: {
      fill: 'none',
      stroke: '#303133',
      'stroke-width': 1,
      rotate: 0, // 初始旋转角度
      remark: '' // 初始化备注为空
    },
    points: [
      { x: x, y: y - height/2 },    // 上
      { x: x + width/2, y: y },     // 右
      { x: x, y: y + height/2 },     // 下
      { x: x - width/2, y: y }      // 左
    ],
    selected: false
  };
};
// 创建返回元素的方法
const createReturnElement = (x: number, y: number) => {
  const rectX = x - 50;
  const rectY = y - 25;
  const rectWidth = 100;
  const rectHeight = 50;

  return {
    id: `return-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
    type: 'g',
    objectType: 'return',
    attrs: {},
    children: [
      {
        type: 'rect',
        attrs: {
          x: rectX,
          y: rectY,
          width: rectWidth,
          height: rectHeight,
          fill: 'white',
          stroke: 'black',
          'stroke-width': 1,
          rx: 5 // 圆角
        }
      },
      {
        type: 'path',
        attrs: {
          d: 'M512 0C229.229617 0 0 229.229617 0 512s229.229617 512 512 512 512-229.230708 512-512S794.769292 0 512 0z m232.727074 640.000818a186.182314 186.182314 0 0 1-186.182314 186.181223 26.996746 26.996746 0 1 1 0-53.992402 131.258275 131.258275 0 0 0 131.258275-131.258275v-69.818231A131.258275 131.258275 0 0 0 558.545851 438.923221H353.280251l127.535 93.090611a27.137474 27.137474 0 1 1-32.116387 43.753122l-186.182314-139.636462a26.996746 26.996746 0 0 1-6.051277-37.701845l6.051277-6.051277 186.182314-139.636463a27.461474 27.461474 0 0 1 37.701845 6.516004 26.530928 26.530928 0 0 1-5.585458 36.771299l-115.433537 88.902609H558.545851A186.182314 186.182314 0 0 1 744.728165 571.113133z',
          stroke: '#67C23A',
          fill: '#1296db',
          'stroke-width': 1,
          'stroke-linecap': 'round',
          'stroke-linejoin': 'round',
           transform: `translate(${rectX + 30}, ${rectY }) scale(0.05)`
        }
      },
      {
        type: 'text',
        attrs: {
          x: rectX + rectWidth / 2,
          y: rectY + rectHeight / 2,
          'text-anchor': 'middle',
          'dominant-baseline': 'middle',
          fill: '#333',
          'font-size': 12,
          'font-weight': 'bold'
        },
        text: ''
      }
    ],
    selected: false,
    returnValue: '' // 返回值属性
  };
};
// 创建新连线
// const createConnection = (x: number, y: number): Connection => {
//   const midX = x + 50;
//   const midY = y;
//   return {
//     id: `conn-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
//     points: [
//       { x, y },
//       { x: midX, y: midY },
//       { x: x + 100, y }
//     ],
//     path: `M${x},${y} L${midX},${midY} L${x + 100},${y}`,
//     stroke: '#000000',
//     strokeWidth: 2,
//     remark: '' // 初始化备注为空
//   };
// };

const getSVGContent = (data: any, x: number, y: number) => {
  const rectX = x - 50;
  const rectY = y - 25;
  const rectWidth = 100;
  const rectHeight = 50;
  const imageUrl = data.componentIconUrl;
  const isTenant = data.isTenant;
  return {
    id: `component-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
    type: 'g', // 使用 <g> 标签包裹 SVG 元素
    objectType: 'component',
    attrs: {}, // 不需要额外的属性
    children: [
      {
        type: 'rect',
        attrs: {
          x: rectX,
          y: rectY,
          width: rectWidth,
          height: rectHeight,
          fill: 'white',
          stroke: 'black', // 边框颜色
          'stroke-width': 1, // 边框宽度
        },
      },
      {
        type: 'image',
        attrs: {
          x: rectX,
          y: rectY,
          width: 16,
          height: 16,
          href: imageUrl,
        },
      },
      {
        type: 'text',
        attrs: {
          x: rectX + rectWidth / 2, // 文本居中
          y: rectY + rectHeight / 2, // 文本居中
          'text-anchor': 'middle', // 水平居中
          'dominant-baseline': 'middle', // 垂直居中
          fill: 'black', // 文本颜色
          'font-size': 10, // 字体大小
          textLength: rectWidth / 2, // 文本长度
          lengthAdjust: 'spacingAndGlyphs', // 调整文本长度
          className: data.className,
          selectedFunctionPoint: '',
          functionPointParams: [],
          isTenant: isTenant,
          returnValueName: '',
          remark: '' // 初始化备注为空
        },
        text: '', // 显示绑定的功能名称
      },
    ],
    selected: false, // 默认未选中
  };
};

// 选中元素
const selectElement = (index: number, event: MouseEvent) => {
  if (event.shiftKey) {
    // 按住 Shift 键多选
    svgElements.value[index].selected = !svgElements.value[index].selected;
  } else {
    clearAllSelections();
    // 单选
    svgElements.value.forEach((element, i) => {
      element.selected = i === index;
    });
  }
  // 更新当前选中的元素
  selectedElement.value = svgElements.value[index];
  // 如果是返回对象，不需要加载功能点
  if (selectedElement.value.objectType === 'return') {
    handleSvgClick(event);
    return;
  }
  // 如果是连线，确保中间的把柄显示
  if (selectedElement.value.objectType  === 'connection') {
    const conn = selectedElement.value;
    if (conn.points.length === 2) {
      // 如果是直线，添加中间点
      const midX = (conn.points[0].x + conn.points[1].x) / 2;
      const midY = (conn.points[0].y + conn.points[1].y) / 2;
      conn.points.splice(1, 0, { x: midX, y: midY });
      conn.path = conn.points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ');
    }
  }else {
    //根据组件类名查询功能点，并将功能点名称赋值给text
    let param = {"className": selectedElement.value.children[2].attrs.className}
    if (selectedElement.value.children[2].attrs.isTenant == 'N') {
      listNoPageSysFunction(param).then(res => {
        functionPoints.value = res.data;
      })
    } else {
      listNoPageSysFunction(param).then(response => {
        functionPoints.value = response.data;
      });
    }
    handleSvgClick(event);
  }
};


// 设置控制点光标样式
const setHandleCursor = () => {
  const svg = document.querySelector('svg');
  if (svg) svg.style.cursor = 'move';
};

// 重置光标样式
const resetCursor = () => {
  const svg = document.querySelector('svg');
  if (svg) svg.style.cursor = '';
};
const svgCanvas = ref<SVGSVGElement | null>(null);

const getSVGCoord = (event: MouseEvent) => {
  if (!svgCanvas.value) return { x: 0, y: 0 };

  const pt = svgCanvas.value.createSVGPoint();
  pt.x = event.clientX;
  pt.y = event.clientY;

  try {
    const svgPt = pt.matrixTransform(svgCanvas.value.getScreenCTM()?.inverse());
    return { x: svgPt.x, y: svgPt.y };
  } catch (e) {
    console.error("坐标转换错误:", e);
    return { x: 0, y: 0 };
  }
};
const handleLineClick = (conn: Connection, event: MouseEvent) => {


  event.stopPropagation();
  event.preventDefault(); // 防止默认行为干扰
  //debugger;
  // 如果正在拖动箭头或控制点，则不处理点击
  // if (isDraggingArrow || draggingIndex !== -1) return;
  if(draggingIndex !=-1) return;


  // 清除其他元素的选中状态
  clearAllSelections();

  // 选中当前线条
  selectedArrow.value = conn;
  if(isDrawingMode.value){
    handleSvgClick(event);
    return;
  }
  // 检查是否点击了控制点（通过事件目标判断）
  const isHandleClick = (event.target as Element)?.classList?.contains('conn-handle');
  const isArrowClick = (event.target as Element)?.tagName === 'path' &&
      (event.target as Element)?.parentElement?.tagName === 'marker';

  // 如果不是点击控制点或箭头，则添加新控制点
  if (!isHandleClick && !isArrowClick) {
    const { x, y } = getSVGCoord(event);
    const nearestIndex = findNearestSegmentIndex(conn, x, y);

    if (nearestIndex >= 0) {
      // 记录操作到撤销栈
      undoStack.value.push(JSON.parse(JSON.stringify(connections.value)));

      // 在最近的线段中间插入新控制点
      conn.points.splice(nearestIndex + 1, 0, { x, y });
      updateConnectionPath(conn);

      // 清空重做栈
      redoStack.value = [];
    }
  }
};

/**
 * 找到距离点击位置最近的线段索引
 * @param conn 连线对象
 * @param x 点击坐标X
 * @param y 点击坐标Y
 * @returns 最近线段的起始点索引（-1表示无效）
 */
const findNearestSegmentIndex = (conn: Connection, x: number, y: number): number => {
  let minDistance = Infinity;
  let nearestIndex = -1;
  const threshold = 10; // 像素阈值，点击位置距离线段最大距离

  for (let i = 0; i < conn.points.length - 1; i++) {
    const p1 = conn.points[i];
    const p2 = conn.points[i + 1];

    // 计算点到线段的距离
    const distance = distanceToSegment(x, y, p1.x, p1.y, p2.x, p2.y);

    // 如果距离在阈值内且是当前最近的点
    if (distance < threshold && distance < minDistance) {
      minDistance = distance;
      nearestIndex = i;
    }
  }

  return nearestIndex;
};
/**
 * 计算点 (x,y) 到线段 (x1,y1)-(x2,y2) 的距离
 */
const distanceToSegment = (
    x: number, y: number,
    x1: number, y1: number,
    x2: number, y2: number
): number => {
  const A = x - x1;
  const B = y - y1;
  const C = x2 - x1;
  const D = y2 - y1;

  const dot = A * C + B * D;
  const lenSq = C * C + D * D;
  let param = -1;

  // 考虑线段长度为0的情况
  if (lenSq !== 0) {
    param = dot / lenSq;
  }

  let xx, yy;

  // 计算垂足坐标
  if (param < 0) {
    xx = x1;
    yy = y1;
  } else if (param > 1) {
    xx = x2;
    yy = y2;
  } else {
    xx = x1 + param * C;
    yy = y1 + param * D;
  }

  // 返回欧几里得距离
  return Math.sqrt((x - xx) ** 2 + (y - yy) ** 2);
};
const updateConnectionPath = (conn: Connection) => {
  // 简单折线：直接连接所有控制点
  conn.path = conn.points.map((p, i) =>
      `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`
  ).join(' ');

  // 如果需要平滑曲线，可改用贝塞尔曲线：
  // conn.path = generateSmoothPath(conn.points);
};
// 清空选中状态
const clearSelection = () => {
  // clearAllSelections();
  // 原有的清除选择逻辑
  selectedArrow.value = null;
};

// 删除选中的元素
const deleteSelectedElement = async (event: KeyboardEvent) => {
  // 只响应Delete键
  if (event.key !== 'Delete') return;

  //1. 优先删除选中的连线
  if (selectedArrow.value) {
    // 记录操作到撤销栈
    undoStack.value.push({
      elements: [...svgElements.value],
      connections: [...connections.value]
    });

    // 过滤掉当前选中的连线
    connections.value = connections.value.filter(conn => conn !== selectedArrow.value);
    selectedArrow.value = null;
    redoStack.value = []; // 清空重做栈
    return;
  }
// 2. 检查选中的菱形
  const selectedDiamonds = diamondElements.value.filter(d => d.selected);
  if (selectedDiamonds.length > 0) {
    try {
      await ElMessageBox.confirm('确定要删除选中的菱形吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      });

      // 记录操作到撤销栈
      undoStack.value.push({
        elements: [...svgElements.value],
        connections: [...connections.value],
        diamonds: [...diamondElements.value]
      });

      // 删除选中的菱形
      diamondElements.value = diamondElements.value.filter(d => !d.selected);
      selectedElement.value = null;
      redoStack.value = [];
      return;
    } catch {
      return; // 用户取消删除
    }
  }
  // 3. 最后检查选中的普通元素
  const selectedElements = svgElements.value.filter(element => element.selected);
  if (selectedElements.length === 0) return;

  try {
    await ElMessageBox.confirm('确定要删除选中的元素吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    });

    // 记录操作到撤销栈
    undoStack.value.push({
      elements: [...svgElements.value],
      connections: [...connections.value]
    });

    // 删除选中的元素
    svgElements.value = svgElements.value.filter(element => !element.selected);
    selectedElement.value = null;
    redoStack.value = []; // 清空重做栈
  } catch (error) {
    console.log('取消删除');
  }
};
// 撤销操作
const undo = () => {
  if (undoStack.value.length > 0) {
    const previousState = undoStack.value.pop();
    redoStack.value.push({
      elements: [...svgElements.value],
      connections: [...connections.value],
      diamonds: [...diamondElements.value]
    });

    svgElements.value = previousState.elements;
    connections.value = previousState.connections;
    diamondElements.value = previousState.diamonds;
  }
};
//重做操作
const redo = () => {
  if (redoStack.value.length > 0) {
    const nextState = redoStack.value.pop();
    undoStack.value.push({
      elements: [...svgElements.value],
      connections: [...connections.value],
      diamonds: [...diamondElements.value]
    });

    svgElements.value = nextState.elements;
    connections.value = nextState.connections;
    diamondElements.value = nextState.diamonds;
  }
};

// 开始调整元素大小
const startResizeElement = (index: number, direction: string, event: MouseEvent) => {
  const element = svgElements.value[index];
  const rect = element.children[0].attrs;
  const image = element.children[1].attrs;

  let lastX = event.clientX;
  let lastY = event.clientY;

  const onMouseMove = (e: MouseEvent) => {
    const deltaX = e.clientX - lastX;
    const deltaY = e.clientY - lastY;

    // 更新上次鼠标位置
    lastX = e.clientX;
    lastY = e.clientY;

    // 根据方向调整元素
    if (direction === 'top-left') {
      rect.x += deltaX;
      rect.y += deltaY;
      rect.width -= deltaX;
      rect.height -= deltaY;
      image.x += deltaX;
      image.y += deltaY;
    } else if (direction === 'top') {
      rect.y += deltaY;
      rect.height -= deltaY;
      image.y += deltaY;
    } else if (direction === 'top-right') {
      rect.y += deltaY;
      rect.width += deltaX;
      rect.height -= deltaY;
      image.y += deltaY;
    } else if (direction === 'right') {
      rect.width += deltaX;
    } else if (direction === 'bottom-right') {
      rect.width += deltaX;
      rect.height += deltaY;
    } else if (direction === 'bottom') {
      rect.height += deltaY;
    } else if (direction === 'bottom-left') {
      rect.x += deltaX;
      rect.width -= deltaX;
      rect.height += deltaY;
      image.x += deltaX;
    } else if (direction === 'left') {
      rect.x += deltaX;
      rect.width -= deltaX;
      image.x += deltaX;
    }

    // 动态调整 SVG 大小
    adjustSVGSize();
  };

  const onMouseUp = () => {
    window.removeEventListener('mousemove', onMouseMove);
    window.removeEventListener('mouseup', onMouseUp);
  };

  window.addEventListener('mousemove', onMouseMove);
  window.addEventListener('mouseup', onMouseUp);
};

// 递归更新所有关联的连线
const updateAllConnectedLines = (elementId: string, deltaX: number, deltaY: number, processedIds = new Set<string>()) => {
  // 避免循环处理
  if (processedIds.has(elementId)) return;
  processedIds.add(elementId);

  // 1. 处理以当前元素为起点或终点的直接连线
  const directConnections = connections.value.filter(conn =>
      conn.startElementId === elementId ||
      conn.endElementId === elementId
  );

  directConnections.forEach(conn => {
    // 更新连线上的对应点
    if (conn.startElementId === elementId) {
      conn.points[0].x += deltaX;
      conn.points[0].y += deltaY;
    }
    if (conn.endElementId === elementId) {
      const lastIndex = conn.points.length - 1;
      conn.points[lastIndex].x += deltaX;
      conn.points[lastIndex].y += deltaY;
    }
    updateConnectionPath(conn);

    // 2. 递归处理以这条连线为起点或终点的其他连线
    updateAllConnectedLines(conn.id, deltaX, deltaY, processedIds);
  });
};
// 开始移动元素
const startMoveElement = (index: number, event: MouseEvent) => {
  const element = svgElements.value[index];
  const rect = element.children[0].attrs;
  const image = element.children[1].attrs;
  const path = element.children[1].attrs;
  const text = element.children[2].attrs;

  let lastX = event.clientX;
  let lastY = event.clientY;

  const onMouseMove = (e: MouseEvent) => {
    const deltaX = e.clientX - lastX;
    const deltaY = e.clientY - lastY;

    // 更新上次鼠标位置
    lastX = e.clientX;
    lastY = e.clientY;

    // 移动元素
    rect.x += deltaX;
    rect.y += deltaY;
    image.x += deltaX;
    image.y += deltaY;
    text.x += deltaX;
    text.y += deltaY;
    if (selectedElement.value.objectType === 'return') {
      // 更新 <path> 的 transform 属性
      path.transform = `translate(${rect.x + 30}, ${rect.y }) scale(0.05)`;
    }
    // 递归更新所有关联的连线
    updateAllConnectedLines(element.id, deltaX, deltaY);

    // 动态调整 SVG 大小
    adjustSVGSize();
  };

  const onMouseUp = () => {
    window.removeEventListener('mousemove', onMouseMove);
    window.removeEventListener('mouseup', onMouseUp);
  };

  window.addEventListener('mousemove', onMouseMove);
  window.addEventListener('mouseup', onMouseUp);
};
// 辅助方法：获取元素的吸附点坐标
const getElementSnapPoint = (element: any) => {
  if (element.objectType  === 'diamond') {
    return {
      x: (element.points[0].x + element.points[2].x)/2,
      y: (element.points[1].y + element.points[3].y)/2
    };
  } else {
    const rect = element.children[0].attrs;
    return {
      x: rect.x + rect.width/2,
      y: rect.y + rect.height/2
    };
  }
};
// 动态调整 SVG 大小
const adjustSVGSize = () => {
  let maxX = 0;
  let maxY = 0;

  svgElements.value.forEach(element => {
    const rect = element.children[0].attrs;
    const right = rect.x + rect.width;
    const bottom = rect.y + rect.height;

    if (right > maxX) maxX = right;
    if (bottom > maxY) maxY = bottom;
  });

  // 增加一定的边距
  const padding = 50;
  svgWidth.value = Math.max(svgWidth.value, maxX + padding);
  svgHeight.value = Math.max(svgHeight.value, maxY + padding);
};

// 开始调整宽度
const startResize = (e: MouseEvent) => {
  isResizing.value = true;
  window.addEventListener('mousedown', handleMouseDown);
  window.addEventListener('mousemove', handleMouseMove);
  window.addEventListener('mouseup', stopResize);
};

// 处理鼠标按下事件
const handleMouseDown = (e: MouseEvent) => {
  lastMoveX.value = e.clientX;
};

// 处理鼠标移动事件
const handleMouseMove = (e: MouseEvent) => {
  if (isResizing.value) {
    const newWidth = e.clientX - lastMoveX.value;
    leftWidth.value += newWidth;
  }
  lastMoveX.value = e.clientX;
};
// 修改 startDragLine 方法
const startDragLine = (connIndex: number, pointIndex: number, e: MouseEvent) => {
  e.stopPropagation();

  // 获取初始SVG坐标
  const startPos = getSVGCoord(e);

  // 记录初始状态
  draggingIndex = connIndex;
  draggingPointIndex = pointIndex;
  lastX = e.clientX;
  lastY = e.clientY;

  // 选中当前连线
  selectedArrow.value = connections.value[connIndex];

  // 记录操作到撤销栈
  undoStack.value.push(JSON.parse(JSON.stringify(connections.value)));

  window.addEventListener('mousemove', onDragLine);
  window.addEventListener('mouseup', stopDragLine);
};


// 停止调整宽度
const stopResize = () => {
  isResizing.value = false;
  lastMoveX.value = 0;
  window.removeEventListener('mousemove', handleMouseMove);
  window.removeEventListener('mouseup', stopResize);
  window.removeEventListener('mousedown', handleMouseDown);
};
//提交组件
const commitComponent = async () => {
  let rootElement = {"svgElements":svgElements.value, "connections":connections.value,"diamondElements":diamondElements.value}
  let data = { "functionId": functionId.value, "designScript": JSON.stringify(rootElement) };
  let res = await updateFunction(data);
  if (res.code == 200) {
    ElMessage({
      message: '保存成功',
      type: 'success'
    });
  } else {
    ElMessage({
      message: res.msg || '保存失败！',
      type: 'error'
    });
  }
};
// 保存组件
const saveComponent = async () => {
  let rootElement = {"svgElements":svgElements.value, "connections":connections.value,"diamondElements":diamondElements.value}
  emit('update:modelValue',JSON.stringify(rootElement))
};
// 添加边界检查方法
const checkBoundary = (x: number, y: number) => {
  const padding = 10; // 保留10像素边距
  return {
    x: Math.max(padding, Math.min(svgWidth.value - padding, x)),
    y: Math.max(padding, Math.min(svgHeight.value - padding, y))
  };
};

// 修改后的 onDragLine 方法
const onDragLine = (e: MouseEvent) => {
  if (draggingIndex === -1) return;

  const { x, y } = getSVGCoord(e);
  const point = connections.value[draggingIndex].points[draggingPointIndex];
  const conn = connections.value[draggingIndex];

  let newX = x;
  let newY = y;


  // 更新点位置
  point.x = newX;
  point.y = newY;
  updateConnectionPath(conn);
};
// 新增状态变量
let isDraggingArrow = false;
let currentDraggingConn: Connection | null = null;
let dragStartPos = { x: 0, y: 0 };
let dragInitialPoints: {x: number, y: number}[] = []; // 用于保存拖动初始位置
// 开始拖动箭头
// 修改 startArrowDrag 方法
const startArrowDrag = (conn: Connection, event: MouseEvent) => {
  event.stopPropagation();

  const { x, y } = getSVGCoord(event);

  // 记录初始状态
  isDraggingArrow = true;
  currentDraggingConn = conn;
  dragStartPos = { x, y };

  // 保存所有控制点的初始位置到临时变量
  dragInitialPoints = conn.points.map(p => ({...p})); // 深拷贝控制点位置

  conn.isDragging = true;
  selectedArrow.value = conn;
  undoStack.value.push(JSON.parse(JSON.stringify(connections.value)));

  const onArrowDrag = (event: MouseEvent) => {
    if (!isDraggingArrow || !currentDraggingConn) return;

    const { x, y } = getSVGCoord(event);
    const deltaX = x - dragStartPos.x;
    const deltaY = y - dragStartPos.y;

    // 更新当前连线的所有控制点位置
    currentDraggingConn.points = dragInitialPoints.map((point, index) => {
      const newPos = checkBoundary(
          point.x + deltaX,
          point.y + deltaY
      );
      return { ...newPos };
    });

    // 递归更新所有关联的连线
    updateAllConnectedLines(conn.id, deltaX, deltaY);

    updateConnectionPath(currentDraggingConn);
  };

  const stopArrowDrag = () => {
    if (currentDraggingConn) {
      currentDraggingConn.isDragging = false;
      updateConnectionPath(currentDraggingConn);
    }
    isDraggingArrow = false;
    currentDraggingConn = null;
    dragInitialPoints = [];
    window.removeEventListener('mousemove', onArrowDrag);
    window.removeEventListener('mouseup', stopArrowDrag);
  };

  window.addEventListener('mousemove', onArrowDrag);
  window.addEventListener('mouseup', stopArrowDrag);
};
// 在 script 部分添加以下代码
const SNAP_THRESHOLD = ref(10); // 吸附阈值(像素)
const isSnappingEnabled = ref(true); // 是否启用吸附功能



// 修改 onArrowDrag 方法
const onArrowDrag = (event: MouseEvent) => {
  if (!isDraggingArrow || !currentDraggingConn) return;

  const { x, y } = getSVGCoord(event);
  const deltaX = x - dragStartPos.x;
  const deltaY = y - dragStartPos.y;

  // 更新所有控制点位置
  currentDraggingConn.points = dragInitialPoints.map((point, index) => {
    const newPos = checkBoundary(
        point.x + deltaX,
        point.y + deltaY
    );
    return { ...newPos };
  });

  updateConnectionPath(currentDraggingConn);
};
// 停止拖动箭头
const stopArrowDrag = () => {
  if (currentDraggingConn) {
    // 检查终点是否可以绑定到元素
    const lastPoint = currentDraggingConn.points[currentDraggingConn.points.length - 1];
    const endElement = findNearestSnapPoint (lastPoint.x, lastPoint.y);

    if (endElement) {
      currentDraggingConn.endElementId = endElement?.elementId || undefined;
    }
    currentDraggingConn.isDragging = false;
    updateConnectionPath(currentDraggingConn);
  }
  //debugger;
  isDraggingArrow = false;
  currentDraggingConn = null;
  dragInitialPoints = []; // 清空临时变量
  window.removeEventListener('mousemove', onArrowDrag);
  window.removeEventListener('mouseup', stopArrowDrag);
};

const stopDragLine = () => {
  if (draggingIndex !== -1) {
    const conn = connections.value[draggingIndex];

    // 最终确认连接关系
    // if (isSnappingEnabled.value) {
    //   // 检查起点
    //   const startSnap = findNearestSnapPoint(
    //       conn.points[0].x,
    //       conn.points[0].y
    //   );
    //   conn.startElementId = startSnap?.elementId || undefined;
    //
    //   // 检查终点
    //   const endSnap = findNearestSnapPoint(
    //       conn.points[conn.points.length - 1].x,
    //       conn.points[conn.points.length - 1].y
    //   );
    //   conn.endElementId = endSnap?.elementId || undefined;
    // }

    // updateConnectionPath(conn);
  }

  draggingIndex = -1;
  draggingPointIndex = -1;
  window.removeEventListener('mousemove', onDragLine);
  window.removeEventListener('mouseup', stopDragLine);
};
// 在startMoveElement和startMoveDiamond方法中添加：
const updateConnectedLines = (id: string) => {
  connections.value.forEach(conn => {
    let needsUpdate = false;

    // 更新起点连接的线
    if (conn.startElementId === id) {
      // 检查是连接元素还是连接线
      if (id.startsWith('component-') || id.startsWith('diamond-')) {
        const element = [...svgElements.value, ...diamondElements.value]
            .find(el => el.id === id);
        if (element) {
          conn.points[0] = getElementCenter(element);
          needsUpdate = true;
        }
      } else if (id.startsWith('conn-')) {
        const connection = connections.value.find(c => c.id === id);
        if (connection) {
          // 连接到另一条连接线的中点
          const midIndex = Math.floor(connection.points.length / 2);
          // 只更新起点，不影响终点
          conn.points[0] = { ...connection.points[midIndex] };
          needsUpdate = true;
        }
      }
    }

    // 更新终点连接的线
    if (conn.endElementId === id) {
      // 检查是连接元素还是连接线
      if (id.startsWith('component-') || id.startsWith('diamond-')) {
        const element = [...svgElements.value, ...diamondElements.value]
            .find(el => el.id === id);
        if (element) {
          const lastIndex = conn.points.length - 1;
          conn.points[lastIndex] = getElementCenter(element);
          needsUpdate = true;
        }
      } else if (id.startsWith('conn-')) {
        const connection = connections.value.find(c => c.id === id);
        if (connection) {
          // 连接到另一条连接线的中点
          const midIndex = Math.floor(connection.points.length / 2);
          const lastIndex = conn.points.length - 1;
          // 只更新终点，不影响起点
          conn.points[lastIndex] = { ...connection.points[midIndex] };
          needsUpdate = true;
        }
      }
    }

    if (needsUpdate) {
      updateConnectionPath(conn);
    }
  });
};

// 获取元素中心坐标的辅助方法
const getElementCenter = (element: any) => {
  if (element.objectType  === 'diamond') {
    return {
      x: (element.points[0].x + element.points[2].x)/2,
      y: (element.points[1].y + element.points[3].y)/2
    };
  } else {
    if(element.children && element.children[0] && element.children[0].attrs) {
      const rect = element.children[0].attrs;
      return {
        x: rect.x + rect.width / 2,
        y: rect.y + rect.height / 2
      };
    }else{
      return {
        x: 0,
        y: 0
      };
    }
  }
};
const findNearestSnapPoint = (x: number, y: number) => {
  let nearestPoint = null;
  let elementId = null;
  let minDistance = SNAP_THRESHOLD.value;

  // 1. 检测连接线吸附点（连接线ID以"conn-"开头）
  connections.value.forEach(conn => {
    // 检查连接线的所有控制点
    conn.points.forEach(point => {
      const distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
      if (distance < minDistance) {
        minDistance = distance;
        nearestPoint = { ...point };
        elementId = conn.id; // 直接使用连接线ID
      }
    });
  });

  // 2. 检测菱形吸附点（菱形ID以"diamond-"开头）
  diamondElements.value.forEach(diamond => {
    diamond.points.forEach(point => {
      const distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
      if (distance < minDistance) {
        minDistance = distance;
        nearestPoint = { ...point };
        elementId = diamond.id;
      }
    });
  });

  // 3. 检测普通元素吸附点（组件ID以"component-"开头）
  svgElements.value.forEach(element => {
    const rect = element.children[0].attrs;
    const points = [
      { x: rect.x, y: rect.y },
      { x: rect.x + rect.width/2, y: rect.y },
      { x: rect.x + rect.width, y: rect.y },
      { x: rect.x, y: rect.y + rect.height },
      { x: rect.x+rect.width, y: rect.y + rect.height/2 },
      { x: rect.x + rect.width, y: rect.y + rect.height },
      { x: rect.x+rect.width/2, y: rect.y + rect.height },
      { x: rect.x, y: rect.y + rect.height/2 },
    ];

    points.forEach(point => {
      const distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
      if (distance < minDistance) {
        minDistance = distance;
        nearestPoint = { ...point };
        elementId = element.id;
      }
    });
  });

  return nearestPoint ? { point: nearestPoint, elementId } : null;
};


const findNearestSnapPointInObject = (o:object,x: number, y: number) => {
  let nearestPoint = null;
  let elementId = null;
  let minDistance = Number.MAX_VALUE;
  if(o.objectType==="diamond"){
    let diamond = o;
    let retPt ;
    // 四个顶点
    diamond.points.forEach(point => {
      const distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
      if (distance < minDistance) {
        minDistance = distance;
        retPt = point;
      }
    });
    return retPt;
  };

  // 2. 检测普通元素吸附点
  if(o.objectType==="component"){
    let element = o;
    const rect = element.children[0].attrs;
    const points = [
      // 八个把柄
      { x: rect.x, y: rect.y },
      { x: rect.x + rect.width/2, y: rect.y },
      { x: rect.x + rect.width, y: rect.y },
      { x: rect.x, y: rect.y + rect.height },
      { x: rect.x+rect.width, y: rect.y + rect.height/2 },
      { x: rect.x + rect.width, y: rect.y + rect.height },
      { x: rect.x+rect.width/2, y: rect.y + rect.height },
      { x: rect.x, y: rect.y + rect.height/2 },
    ];
    let pt ;
    points.forEach(point => {
      const distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
      if (distance < minDistance) {
        minDistance = distance;
        pt = point;
        elementId = element.id;
      }
    });
    return pt;
  };

  return null;
};

// 拖拽状态
let draggingIndex = -1;
let draggingPointIndex = -1;
let lastX = 0;
let lastY = 0;

// 功能点数据
const functionPoints = ref([]);

// 功能点参数数据
const functionPointParams = ref([]);

// 当前选中的功能点
const selectedFunctionPoint = ref(null);
// 新增响应式数据
const returnValueName = ref(''); // 返回值名称
/**
 * 检查返回值是否存在
 * @param returnName
 */
function isExistReturnName(returnName: string) {
  for(let i=0;i<svgElements.value.length;i++){
    if(svgElements.value[i].children[2].attrs.returnValueName === returnName) {
      return true;
    }
  }
  return false;
}

// 处理功能点选择变化
const handleFunctionPointChange = (functionCode) => {
  // 根据选中的功能点加载参数列表
  loadFunctionPointParams(functionCode);
  //回填默认的返回值名称
  let functionName='';

  for(let i=0;i< functionPoints.value.length;i++){
    let  point=functionPoints.value[i];
    if(point.functionCode==functionCode){
      functionName=point.functionName;
      break;
    }
  }
  if(functionName!='') {
    let returnName = functionName+'返回值';

    //判断名称是否存在
    let i=1;
    while(isExistReturnName(returnName)){
      returnName = functionName+'返回值'+i;
      i++;
    }
    selectedElement.value.children[2].attrs.returnValueName = returnName;
  }
};

// 模拟加载功能点参数
const loadFunctionPointParams = async (functionCode) => {
  let parameter = { "functionCode": functionCode }
  let temp: AxiosResponse<any>;
  if (selectedElement.value.children[2].attrs.functionPointParams.length == 0) {
    if (selectedElement.value.children[2].attrs.isTenant == 'Y') {
      temp = await listParametersNoPage(parameter);
    } else {
      temp = await listSysFunctionParameters(parameter);
    }
    // 设置参数列表
    functionPointParams.value = temp.data || [];
    returnValueName.value = ''; // 切换功能点时清空返回值
    selectedElement.value.children[2].attrs.functionPointParams = functionPointParams.value;
  }
};

// 组件挂载时获取数据
onMounted(() => {
  fetchToolbarData();
  loadDesignData();

  // 默认加载第一个功能点的参数
  if (functionPoints.value.length > 0) {
    selectedFunctionPoint.value = functionPoints.value[0].functionCode;
    loadFunctionPointParams(selectedFunctionPoint.value);
  }
});

// 组件卸载时移除事件监听器
onUnmounted(() => {
  window.removeEventListener('keydown', deleteSelectedElement);
});
// 处理线条双击（新增控制点）
const handleLineDoubleClick = (conn: Connection, event: MouseEvent) => {
  event.stopPropagation();

  // 获取SVG坐标
  const { x, y } = getSVGCoord(event);

  // 找到最近的线段索引
  const nearestIndex = findNearestSegmentIndex(conn, x, y);

  if (nearestIndex >= 0) {
    // 在最近的线段中间插入新控制点
    conn.points.splice(nearestIndex + 1, 0, { x, y });
    updateConnectionPath(conn);

    // 记录操作到撤销栈
    undoStack.value.push(JSON.parse(JSON.stringify(connections.value)));
  }
};

// 处理控制点双击（删除控制点）
const deleteControlPoint = (conn: Connection, pointIndex: number, event: MouseEvent) => {
  event.stopPropagation();

  // 至少保留2个控制点（起点和终点）
  if (conn.points.length <= 2) return;

  // 删除指定控制点
  conn.points.splice(pointIndex, 1);
  updateConnectionPath(conn);

  // 记录操作到撤销栈
  undoStack.value.push(JSON.parse(JSON.stringify(connections.value)));
};
// 选中菱形
const selectDiamond = (index: number, event: MouseEvent) => {
  event.stopPropagation();
  clearAllSelections();
  // 设置当前菱形为选中状态
  diamondElements.value[index].selected = true;
  selectedElement.value = {
    ...diamondElements.value[index],
    objectType: 'diamond' // 确保type属性正确设置
  };

  // 强制更新视图
  diamondElements.value = [...diamondElements.value];
  handleSvgClick(event);
};
const clearAllSelections = () => {
  // 清除SVG元素的选中状态
  if(svgElements.value) {
    svgElements.value.forEach(element => {
      element.selected = false;
    });
  }

  // 清除菱形的选中状态
  if(diamondElements.value) {
    diamondElements.value.forEach(diamond => {
      diamond.selected = false;
    });
  }
  // 清除连线的选中状态
  selectedArrow.value = null;

  // 清除当前选中的元素
  selectedElement.value = null;
};
// 边中点调整（保持对称性）
const startResizeDiamondEdge = (index: number, edgeIndex: number, event: MouseEvent) => {
  const diamond = diamondElements.value[index];
  const center = {
    x: (diamond.points[0].x + diamond.points[2].x)/2,
    y: (diamond.points[1].y + diamond.points[3].y)/2
  };

  let lastPos = { x: event.clientX, y: event.clientY };

  const onMouseMove = (e: MouseEvent) => {
    const deltaX = e.clientX - lastPos.x;
    const deltaY = e.clientY - lastPos.y;
    lastPos = { x: e.clientX, y: e.clientY };

    // 根据边类型调整
    if (edgeIndex % 2 === 0) { // 上下边（垂直调整）
      diamond.points[edgeIndex].y += deltaY;
      diamond.points[(edgeIndex+1)%4].y += deltaY;
    } else { // 左右边（水平调整）
      diamond.points[edgeIndex].x += deltaX;
      diamond.points[(edgeIndex+1)%4].x += deltaX;
    }

    // 保持对角线垂直平分
    diamond.points[(edgeIndex+2)%4].x = center.x * 2 - diamond.points[edgeIndex].x;
    diamond.points[(edgeIndex+2)%4].y = center.y * 2 - diamond.points[edgeIndex].y;
  };
  //1
  const onMouseUp = () => {
    window.removeEventListener('mousemove', onMouseMove);
    window.removeEventListener('mouseup', onMouseUp);
  };

  window.addEventListener('mousemove', onMouseMove);
  window.addEventListener('mouseup', onMouseUp);
};
</script>

<style scoped>
.app-container {
  display: flex;
  flex-direction: row;
  height: 100vh;
}

.left-panel {
  /*flex: 0 0 auto; !* 固定宽度 *!*/
  /*overflow-y: auto; !* 允许滚动 *!*/
  width: 200px;
  padding: 10px;
  background: #f0f0f0;
}

.splitter {
  width: 5px;
  background-color: #ccc;
  cursor: ew-resize; /* 调整宽度光标 */
}

.right-panel {
  flex: 1; /* 占据剩余空间 */
  min-height: 100vh;
  padding: 20px;
  overflow: auto; /* 启用滚动条 */
}

.svg-container {
  width: 100%; /* 占满右侧面板宽度 */
  height: calc(100vh - 40px); /* 减去 padding */
  overflow: auto; /* 允许横向和纵向滚动 */
  border: 1px solid #ccc; /* 可选：为容器添加边框 */
  padding: 0;
  margin: 0;
}

svg {
  display: block; /* 确保 SVG 是块级元素 */
  overflow: visible; /* 确保 SVG 内容不会被裁剪 */
}

.property-panel {
  width: 300px; /* 固定宽度 */
  margin-left: 10px; /* 与画布之间的间距 */
  border: 1px solid #ccc;
  border-radius: 4px;
  overflow-y: auto; /* 允许滚动 */
}

.empty-tip {
  text-align: center;
  color: #999;
  padding: 20px;
}

/* 在样式部分新增样式 */
.el-form-item__label {
  font-weight: bold;
  color: #606266;
}

.el-input__inner {
  border-radius: 4px;
}

.active-line {
  stroke: #409EFF !important;
  stroke-width: 3px !important;
  animation: pulse 1.5s infinite;
}
@keyframes pulse {
  0% { r: 4; }
  50% { r: 6; }
  100% { r: 4; }
}
.conn-line:hover {
  stroke: #409EFF;
  stroke-width: 3px;
  cursor: pointer; /* 悬停时显示指针光标 */
}
.conn-handle:hover {
  fill: red !important;
  cursor: pointer;
}
.conn-handle {
  fill: #409EFF;
  r: 5;
  transition: opacity 0.2s;
  pointer-events: all;
}

g:hover .conn-handle, .conn-handle.dragging {
  opacity: 1;
}
.conn-line {
  transition: stroke 0.2s, stroke-width 0.2s;
  pointer-events: visiblePainted; /* 必须项 */
}

.conn-line:active {
  stroke-width: 4px !important;
}
/* 新增拖动状态样式 */
.dragging-line {
  stroke-dasharray: 5, 5;
  opacity: 0.8;
}
/* 箭头拖动热区 */
marker path {
  pointer-events: all;
}


/* 菱形属性面板特定样式 */
.diamond-properties .el-form-item {
  margin-bottom: 18px;
}

.diamond-properties .el-slider {
  width: 90%;
  margin-left: 10px;
}

.diamond-properties .el-input-number {
  width: 120px;
}


/* 新增连线条件表达式样式 */
.connection-condition {
  font-size: 10px;
  fill: #333 !important;
  text-shadow:
      0 0 2px white,
      0 0 2px white,
      0 0 2px white; /* 白色描边增强对比度 */
  pointer-events: none;
  user-select: none;
}
/* 添加返回对象的样式 */
.return-element rect {
  fill: #f0f9eb;
  stroke: #67C23A;
}

.return-element path {
  stroke: #67C23A;
}

.return-element text {
  fill: #333;
  font-weight: bold;
}
</style>
